/*******************************************************************************
*  file    : uzmainwindow.cpp
*  created : 06.05.2013
*  author  : 
*******************************************************************************/

#include "uzmainwindow.h"
#include "ui_uzmainwindow.h"
#include "deferredresult.hpp"

#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkCookieJar>
#include <QNetworkCookie>
#include <QUrlQuery>
#include <QCompleter>

#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonParseError>

#include <QList>
#include <QDebug>
#include <qlogger.hpp>

namespace {
QLogger* l_ = QLoggerEngine::getLogger("core");
}

uzMainWindow::uzMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::uzMainWindow),
    ticket_info_id()
{
    ui->setupUi(this);
    ui->dateEdit->setDate(QDate::currentDate());

    accessManager_ = new QNetworkAccessManager(this);
    getter_ = new UzDataGetter(this);

    connect(ui->loadUzAct    , SIGNAL(triggered()), this, SLOT(loadUzPage()) );
    connect(ui->searchCityAct, SIGNAL(triggered()), this, SLOT(loadCities()) );
    connect(ui->getTicketAct , SIGNAL(triggered()), this, SLOT(loadTicketInfo())   );

    connect(ui->fromCombo, SIGNAL(editTextChanged  (QString)),
            this,          SLOT  (onEditTextChanged(QString))  );
    connect(ui->toCombo  , SIGNAL(editTextChanged  (QString)),
            this,          SLOT  (onEditTextChanged(QString))  );

    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(requestTicketsInfo()) );

    ui->fromCombo->completer()->setMaxVisibleItems(5);
    ui->fromCombo->completer()->setCompletionMode(QCompleter::PopupCompletion);
    ui->toCombo->completer()->setMaxVisibleItems(5);
    ui->toCombo->completer()->setCompletionMode(QCompleter::PopupCompletion);
}

uzMainWindow::~uzMainWindow()
{
    delete ui;
}

void uzMainWindow::loadUzPage()
{
    QNetworkRequest request(QUrl("http://booking.uz.gov.ua/ru/"));
    QNetworkReply* reply = accessManager_->get(request);
    connect(reply, SIGNAL(finished()), this, SLOT(finishLoad()));
}

void uzMainWindow::finishLoad()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(const_cast<QObject*>(sender()));
    QTextEdit* textEdit = ui->textEdit;
    textEdit->setAttribute(Qt::WA_DeleteOnClose);
    textEdit->show();
    textEdit->setPlainText(reply->readAll());
    reply->deleteLater();

    // выгребаем печеньки
    QList<QNetworkCookie> cookies =
            accessManager_->cookieJar()->cookiesForUrl(QUrl("http://booking.uz.gov.ua/ru/"));
    logInfo(l_)<<tr("Печеньки для ")<<"http://booking.uz.gov.ua/ru/";
    foreach (const QNetworkCookie& nc, cookies) {
            logInfo(l_)<<QString(nc.name())<<":"<<QString(nc.value());
        }

    cookies =
            accessManager_->cookieJar()->cookiesForUrl(QUrl("http://booking.uz.gov.ua/"));
    logInfo(l_)<<tr("Печеньки для ")<<"http://booking.uz.gov.ua/";
    foreach (const QNetworkCookie& nc, cookies) {
            logInfo(l_)<<QString(nc.name())<<":"<<QString(nc.value());
        }
}

void uzMainWindow::loadCities()
{
    // /ru/purchase/station/%D0%BB%D1%83/
    // http://booking.uz.gov.ua/ru/purchase/station/Ки
    QUrl url = QUrl(tr("http://booking.uz.gov.ua/ru/purchase/station/Ки"));
    logDebug(l_)<<"Url : "<<url.toString();

    QNetworkRequest request(url);
    request.setRawHeader("Host", "booking.uz.gov.ua");
    request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:20.0) Gecko/20100101 Firefox/20.0");
    request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
    request.setRawHeader("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3");
    request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
    request.setRawHeader("Referer", "http://booking.uz.gov.ua/ru/");
    request.setRawHeader("Connection", "keep-alive");
    request.setRawHeader("Pragma", "no-cache");
    request.setRawHeader("Content-Length", "0");

    QNetworkReply* reply = accessManager_->get(request);
    connect(reply, SIGNAL(finished()), this, SLOT(finishLoadCities()));
}

void uzMainWindow::finishLoadCities()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(const_cast<QObject*>(sender()));
    QTextEdit* textEdit = ui->textEdit;
    textEdit->setAttribute(Qt::WA_DeleteOnClose);
    QByteArray reply_data = reply->readAll();
    textEdit->setPlainText(reply_data);
    reply->deleteLater();

    QJsonParseError jpe;
    QJsonDocument jd = QJsonDocument::fromJson(reply_data, &jpe);
    if(jpe.error == QJsonParseError::NoError)
        {
            logInfo(l_)<<"we have JSON .";
            textEdit->setPlainText(jd.toJson());
            if(jd.isObject())
                {
                    logInfo(l_)<<"json is Object!";
                    QJsonValue jsv = jd.object().value("value");
                    if(jsv.isArray())
                        {
                            logInfo(l_)<<"json value VALUE is array";

                            foreach (const QJsonValue& j, jsv.toArray())
                                {
                                    if(j.isObject())
                                        {
                                            logDebug(l_)
                                                    <<j.toObject().value("title").toString()<<":\t"
                                                    <<QString::number( static_cast<int>(j.toObject().value("station_id").toDouble()));
                                        }
                                }
                        }

                }

        }
}

void uzMainWindow::loadTicketInfo()
{
    QUrl url = QUrl(tr("http://booking.uz.gov.ua/ru/purchase/search/"));
    logDebug(l_)<<"Url : "<<url.toString();

    QNetworkRequest request(url);
    request.setRawHeader("Host", "booking.uz.gov.ua");
    request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:20.0) Gecko/20100101 Firefox/20.0");
    request.setRawHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
    request.setRawHeader("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3");
    request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
    request.setRawHeader("Referer", "http://booking.uz.gov.ua/ru/");
    request.setRawHeader("Connection", "keep-alive");
    request.setRawHeader("Pragma", "no-cache");
    request.setRawHeader("GV-Ajax", "1");
    request.setRawHeader("GV-Referer", "http://booking.uz.gov.ua/ru/");
    request.setRawHeader("GV-Screen", "1280x800");
    request.setRawHeader("GV-Unique-Host", "1");

    QByteArray data;

    data.append("date_dep=29.05.2013&");
    data.append("station_from=");
    data.append(QByteArray("Луцк").toPercentEncoding());
    data.append("&");
    data.append("station_id_from=2218060&");
    data.append("station_id_till=2200001&");

    data.append("station_till=");
    data.append(QByteArray("Киев").toPercentEncoding());
    data.append("&");

    data.append("time_dep=00:00&");
    data.append("search=");

    qDebug()<<data;

    //request.setRawHeader("Content-Length",QString("%1").arg(params.query().toLatin1().size()).toLatin1());
    request.setRawHeader("Content-Length",QByteArray::number(data.size()));

    QNetworkReply* reply = accessManager_->post(request,data/*params.query().toLatin1()*/);
    //qDebug()<<"params:"<<params.query();
    connect(reply, SIGNAL(finished()), this, SLOT(finishLoadTicketInfo()));
}

void uzMainWindow::finishLoadTicketInfo()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(const_cast<QObject*>(sender()));
    QTextEdit* textEdit = ui->textEdit;
    textEdit->setAttribute(Qt::WA_DeleteOnClose);

    if(reply->error() != QNetworkReply::NoError)
        {
            logError(l_)<<"Request Error. "<<reply->errorString();
        }

    QByteArray reply_data = reply->readAll();
    textEdit->setPlainText(reply_data);
    reply->deleteLater();

    QJsonParseError jpe;
    QJsonDocument jd = QJsonDocument::fromJson(reply_data, &jpe);
    if(jpe.error == QJsonParseError::NoError)
        {
            logInfo(l_)<<"we have JSON .";
            textEdit->setPlainText(jd.toJson());
            if(jd.isArray())
                {
                    QJsonArray ja = jd.array();
                    foreach (const QJsonValue& jsv, ja)
                        {
                            if(jsv.isArray())
                                {

                                }
                            if(jsv.isObject())
                                {
                                    logInfo(l_)<<jsv.toObject().value("title").toString()
                                              <<jsv.toObject().value("station_id").toString();
                                }
                        }
                }
            else if(jd.isObject())
                {
                    logInfo(l_)<<"json is Object!";
                    QJsonValue jsv = jd.object().value("value");
                    if(jsv.isArray())
                        {
                            logInfo(l_)<<"json value VALUE is array";

                            foreach (const QJsonValue& j, jsv.toArray())
                                {
                                    if(j.isObject())
                                        {
                                            logDebug(l_)
                                                    <<j.toObject().value("title").toString()<<":\t"
                                                    <<QString::number( static_cast<int>(j.toObject().value("station_id").toDouble()));
                                        }
                                }
                        }

                }

    }
}

void uzMainWindow::onEditTextChanged(const QString &text)
{
    QComboBox* combo = qobject_cast<QComboBox*>(const_cast<QObject*>(sender()));
    if ( combo == 0 )
        {
            logError(l_)<<"No combo for edit text changed";
            return;
        }

    if ( (combo->count() == 0 && text.size() == 2) ||
         (combo->count() && (combo->itemText(0).left(2).toUpper() != text.left(2).toUpper())) )
        {
            DeferredResult * res = new DeferredResult;
            res->setCombo(combo);
            res->setRequest(text.left(2).toUpper());
            connect(getter_, SIGNAL(citiesLoaded(QString)), res, SLOT(onCitiesLoaded(QString))  );
            connect(res, SIGNAL(citiesLoaded()), this, SLOT(onCitiesLoaded())  );
            getter_->requestCities(text.left(2).toUpper());
        }
}

void uzMainWindow::onCitiesLoaded()
{
    DeferredResult * res = qobject_cast<DeferredResult *>(const_cast<QObject*>(sender()));
    if(res == 0)
        {
            return;
        }
    QVector<CityData> dat = getter_->cities( res->request() );
    if(dat.size())
        {
            QComboBox* combo = 0;
            if(ui->fromCombo == res->combo() )
                combo = ui->fromCombo;
            else if (ui->toCombo == res->combo())
                combo = ui->toCombo;
            else
                {
                    return;
                }
            QString cur_text = combo->currentText();
            if(combo->count())
                combo->clear();
            combo->addItem(cur_text);
            foreach(const CityData& cd, dat)
                {
                    combo->addItem(cd.name, cd.id);
                }
        }
    res->deleteLater();
}

void uzMainWindow::requestTicketsInfo()
{
    TicketInfo ti;
    ti.from    = ui->fromCombo->itemText(ui->fromCombo->currentIndex()).toLocal8Bit();
    ti.from_id = ui->fromCombo->itemData(ui->fromCombo->currentIndex()).toString().toLocal8Bit();
    ti.to      = ui->toCombo->itemText(ui->toCombo->currentIndex()).toLocal8Bit();
    ti.to_id   = ui->toCombo->itemData(ui->toCombo->currentIndex()).toString().toLocal8Bit();
    ti.date    = ui->dateEdit->date().toString("dd.MM.yyyy").toLocal8Bit();
    ti.id      = ticket_info_id++; // id запроса

    TrainDataDeferredResult* result = new TrainDataDeferredResult(getter_, ti.id, this);
    connect(getter_, SIGNAL(trainDataReady(int)), result, SLOT(onTrainDataReady(int))  );
    connect(result,  SIGNAL(trainDataReady()   ), this  , SLOT(onTrainData()        )  );
    getter_->requestTicketInfo(ti);
}

void uzMainWindow::onTrainData()
{
    TrainDataDeferredResult* res = qobject_cast<TrainDataDeferredResult *>(const_cast<QObject*>(sender()));
    if( res == 0 )
        return;

    logInfo(l_)<<Q_FUNC_INFO;
}


